package com.motu.monstercity.server.game.logic;

import com.motu.monstercity.server.game.base.AllParam;
import com.motu.monstercity.server.game.base.CommonUtils;
import com.motu.monstercity.server.game.commondata.act.ActWord;
import com.motu.monstercity.server.game.commondata.system.*;
import com.motu.vertx.module.utility.mysql.MysqlClient;
import com.motu.vertx.module.utility.mysql.MysqlTool;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class GameBaseData {
    public final static Logger logger = LoggerFactory.getLogger(GameBaseData.class);
    private static JsonObject paramsClientObject = new JsonObject();// 参数配置下发给客户端
    private static ConcurrentHashMap<Integer, JsonObject> functionClientMap = new ConcurrentHashMap<>();// 客户端功能开关
    private static ConcurrentHashMap<Integer, SystemOpen> systemOpenList = new ConcurrentHashMap<Integer, SystemOpen>();// 系统模块解锁
    private static ConcurrentHashMap<Integer, SystemWord> systemWordMap = new ConcurrentHashMap<>(); // 服务端文字
    private static ConcurrentHashMap<Integer, ActWord> actWordMap = new ConcurrentHashMap<>(); // 后台服务端文字
    private static ConcurrentHashMap<String, Integer> actWordHashcodeList = new ConcurrentHashMap<>();
    private static ConcurrentHashMap<Integer, UserExp> userExpMap = new ConcurrentHashMap<>(); // 玩家升级经验表
    private static ConcurrentHashMap<Integer, DecorateMain> decorateMainMap = new ConcurrentHashMap<>(); // 玩家装配配置表,头像,头像框
    private static ConcurrentHashMap<Integer, AdvideoMain> advideoMainMap = new ConcurrentHashMap<>(); // 广告配置表






    // 公共数据初始化
    public static void init(List<Future> futures) {
        futures.add(initParams());
        futures.add(initFunctionClient());
        futures.add(initSystemOpen());
        futures.add(initSystemWord());
        futures.add(initActWord());
        futures.add(initUserExp());
        futures.add(initDecorateMain());
        futures.add(initAdvideoMain());
    }

    // 初始化allparam  params和params_client两表合并, common库和server库合并,相同的server库会覆盖common库
    public static Future<Void> initParams() {
        Promise<Void> promise = Promise.promise();
        String sql = "select name,value from params union select name,value from params_client;";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getCommonPool(), sql, new JsonArray(), res -> {
            if (res.succeeded()) {
                JsonArray list = res.result();
                logger.info("initParams size:" + list.size());
                Class<AllParam> clazz = AllParam.class;// 通过反射修改Function的变量
                reflectParam(clazz, list);
                MysqlTool.queryJsonArrayFromDb(MysqlClient.getServerPool(), sql, new JsonArray(), res2 -> {
                    if (res2.succeeded()) {
                        JsonArray list2 = res2.result();
                        JsonObject tmp = new JsonObject();
                        for (int i = 0; i < list2.size(); i++) {
                            JsonObject obj = list2.getJsonObject(i);
                            tmp.put(obj.getString("name"), obj.getString("value"));
                        }
                        logger.info("initParams2 size:" + list.size());
                        reflectParam(clazz, list2);
                        paramsClientObject = tmp;
                        promise.complete();
                    } else {
                        logger.error(res2.cause().getMessage());
                        promise.fail(res2.cause());
                    }
                });
            } else {
                logger.error(res.cause().getMessage());
                promise.fail(res.cause());
            }
        });
        return promise.future();
    }

    // 配置时字符串用; 分号隔开
    private static void reflectParam(Class<AllParam> clazz, JsonArray list) {
        for (int i = 0, size = list.size(); i < size; i++) {
            JsonObject obj = list.getJsonObject(i);
            String name = obj.getString("name");
            String value = obj.getString("value");
            try {
                Field field = clazz.getDeclaredField(name);
                if (field.getType() == int.class) {
                    field.set(clazz, Tool.stringToInt(value));
                } else if (field.getType() == int[].class) {
                    field.set(clazz, Tool.strToIntArray(value, ";"));
                } else if (field.getType() == long[].class) {
                    field.set(clazz, Tool.strToLongArray(value, ";"));
                }else if (field.getType() == String[].class) {
                    field.set(clazz, value.replace(" ", "").split(";"));
                } else if (field.getType() == double[].class) {
                    field.set(clazz, Tool.strToDoubleArray(value, ";"));
                } else if (field.getType() == String.class) {
                    field.set(clazz, value);
                } else if (field.getType() == double.class) {
                    field.set(clazz, Double.parseDouble(value));
                } else if (field.getType() == long.class) {
                    field.set(clazz, Long.parseLong(value));
                }
            } catch (NoSuchFieldException ne){
				logger.error("initParams error【" + name + "】参数未定义");
			} catch (Exception e) {
                logger.error("initParams error i = " + i + " name = " + name + " value = " + value);
                if (name.indexOf(' ') != -1) {
                    logger.error(name + "参数名中有空格!!!!");
                }
                if (value.indexOf(' ') != -1) {
                    logger.error(value + "参数数值中有空格!!!!");
                }
            }
        }
    }

    public static JsonObject getParamsClientObject() {
        return paramsClientObject;
    }

    /***
     * 初始化客户端功能开关
     */
    public static Future<Void> initFunctionClient() {
        Promise<Void> fut = Promise.promise();
        String sql = "SELECT * FROM function_client;";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getServerPool(), sql, new JsonArray(), res->{
            if (res.succeeded()) {
                JsonArray list = res.result();
                logger.info("initFunctionClient size:"+list.size());
                ConcurrentHashMap<Integer, JsonObject> temp = new ConcurrentHashMap<>();
                for (int i = 0; i < list.size(); i++) {
                    JsonObject obj = list.getJsonObject(i);
                    temp.put(obj.getInteger("id"), obj);
                }
                functionClientMap = temp;
                fut.complete();
            } else {
                logger.error(res.cause().getMessage());
                fut.fail(res.cause());
            }
        });
        return fut.future();
    }

    public static ConcurrentHashMap<Integer, JsonObject> getFunctionClientMap(){
        return functionClientMap;
    }

    public static JsonObject getFunctionClient(int id) {
        if (functionClientMap.containsKey(id)) {
            return functionClientMap.get(id);
        } else {
            return null;
        }
    }

    public static Future<Void> initSystemOpen() {
        Promise<Void> promise = Promise.promise();
        String sql = "select * from system_open;";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getCommonPool(), sql, new JsonArray(), res -> {
            if (res.succeeded()) {
                ConcurrentHashMap<Integer, SystemOpen> tmp = new ConcurrentHashMap<Integer, SystemOpen>();
                JsonArray list = res.result();
                logger.info("initSystemOpen size:" + list.size());
                for (int i = 0; i < list.size(); i++) {
                    SystemOpen system_open = new SystemOpen(list.getJsonObject(i));
                    tmp.put(system_open.getId(), system_open);
                }
                systemOpenList.clear();
                systemOpenList = tmp;
                promise.complete();
            } else {
                logger.error(res.cause().getMessage());
                promise.fail(res.cause());
            }
        });
        return promise.future();
    }

    public static SystemOpen getSystemOpen(int key) {
        if (systemOpenList.containsKey(key)) {
            return systemOpenList.get(key);
        } else {
            return null;
        }
    }

    public static ConcurrentHashMap<Integer, SystemOpen> getSystemOpenList() {
        return systemOpenList;
    }

    /**
     * 初始化服务端文字
     */
    public static Future<Void> initSystemWord() {
        String table = "system_word";
        Promise promise = Promise.promise();
        String sql = "select * from " + table + ";";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getCommonPool(), sql, new JsonArray(), res -> {
            if (res.succeeded()) {
                try {
                    ConcurrentHashMap<Integer, SystemWord> tmp = new ConcurrentHashMap<>();
                    JsonArray result = res.result();
                    logger.info("init " + table + " size:" + result.size());
                    for (int i = 0; i < result.size(); i++) {
                        SystemWord entity = new SystemWord(result.getJsonObject(i));
                        tmp.put(entity.getId(), entity);
                    }
                    systemWordMap = tmp;
                    promise.complete();
                } catch (Exception e) {
                    logger.error("init " + table + " error exception:" + Tool.getException(e));
                    promise.fail(e);
                }
            } else {
                logger.error(res.cause().getMessage());
                promise.fail(res.cause());
            }
        });
        return promise.future();
    }

    public static SystemWord getSystemWord(int id) {
        SystemWord result = systemWordMap.get(id);
        if (result == null) {
            logger.error("getSystemWord error key = " + id);
        }
        return result;
    }
    public static ConcurrentHashMap<Integer, SystemWord> getSystemWordMap() { return systemWordMap; }


    /**
     * 初始化玩家升级经验表
     */
    public static Future<Void> initUserExp() {
        String table = "user_exp";
        Promise promise = Promise.promise();
        String sql = "select * from " + table + ";";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getCommonPool(), sql, new JsonArray(), res -> {
            if (res.succeeded()) {
                try {
                    ConcurrentHashMap<Integer, UserExp> tmp = new ConcurrentHashMap<>();
                    JsonArray result = res.result();
                    logger.info("init " + table + " size:" + result.size());
                    for (int i = 0; i < result.size(); i++) {
                        UserExp entity = new UserExp(result.getJsonObject(i));
                        tmp.put(entity.getLevel(), entity);
                    }
                    userExpMap = tmp;
                    promise.complete();
                } catch (Exception e) {
                    logger.error("init " + table + " error exception:" + Tool.getException(e));
                    promise.fail(e);
                }
            } else {
                logger.error(res.cause().getMessage());
                promise.fail(res.cause());
            }
        });
        return promise.future();
    }

    public static UserExp getUserExp(int id) {
        UserExp result = userExpMap.get(id);
        if (result == null) {
            logger.error("getUserExp error key = " + id);
        }
        return result;
    }
    public static ConcurrentHashMap<Integer, UserExp> getUserExpMap() { return userExpMap; }

    /**
     * 初始化后台服务端文字
     */
    public static Future<Void> initActWord() {
        Promise<Void> promise = Promise.promise();
        String sql = "select * from act_word;";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getServerPool(), sql, new JsonArray(), res -> {
            if (res.succeeded()) {
                ConcurrentHashMap<Integer, ActWord> tmp = new ConcurrentHashMap<>();
                ConcurrentHashMap<String, Integer> tmpHash = new ConcurrentHashMap<>();
                JsonArray list = res.result();
                logger.info("initActWord size:" + list.size());
                for (int i = 0; i < list.size(); i++) {
                    ActWord entity = new ActWord(list.getJsonObject(i));
                    tmp.put(entity.getId(), entity);
                    tmpHash.put(entity.getHashcode().toLowerCase(), entity.getId());
                }
                actWordMap = tmp;
                actWordHashcodeList = tmpHash;
                promise.complete();
            } else {
                logger.error(res.cause().getMessage());
                promise.fail(res.cause());
            }
        });
        return promise.future();
    }


    public static ActWord getActWord(int id) {
        ActWord result = actWordMap.get(id);
        if (result == null) {
            logger.error("getActWord error key = " + id);
        }
        return result;
    }
    public static ConcurrentHashMap<Integer, ActWord> getActWordMap() { return actWordMap; }

    /**
     * 更新内存中的act_word多个id数据
     */
    public static void updateActWordByIds(int... ids) {
        String idsParam = CommonUtils.intArrayToString(ids, ",");
        String sql = "SELECT * FROM act_word WHERE id IN (" + idsParam + ");";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getServerPool(), sql, new JsonArray(), res -> {
            if (res.succeeded()) {
                JsonArray list = res.result();
                logger.info("updateActWordByIds ids" + idsParam + " size:" + list.size());
                for (int i = 0; i < list.size(); i++) {
                    ActWord entity = new ActWord(list.getJsonObject(i));
                    // 把旧的hashcode数据处理了
                    ActWord oldEntity = actWordMap.get(entity.getId());
                    if (oldEntity != null) {
                        actWordHashcodeList.remove(entity.getHashcode());
                    }
                    // 新的加入内存
                    actWordMap.put(entity.getId(), entity);
                    actWordHashcodeList.put(entity.getHashcode(), entity.getId());
                }
            } else {
                logger.error(res.cause().getMessage());
            }
        });
    }

    /**
     * 初始化玩家装配配置表,头像,头像框
     */
    public static Future<Void> initDecorateMain() {
        String table = "decorate_main";
        Promise promise = Promise.promise();
        String sql = "select * from " + table + ";";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getCommonPool(), sql, new JsonArray(), res -> {
            if (res.succeeded()) {
                try {
                    ConcurrentHashMap<Integer, DecorateMain> tmp = new ConcurrentHashMap<>();
                    JsonArray result = res.result();
                    logger.info("init " + table + " size:" + result.size());
                    for (int i = 0; i < result.size(); i++) {
                        DecorateMain entity = new DecorateMain(result.getJsonObject(i));
                        tmp.put(entity.getId(), entity);
                    }
                    decorateMainMap = tmp;
                    promise.complete();
                } catch (Exception e) {
                    logger.error("init " + table + " error exception:" + Tool.getException(e));
                    promise.fail(e);
                }
            } else {
                logger.error(res.cause().getMessage());
                promise.fail(res.cause());
            }
        });
        return promise.future();
    }

    public static DecorateMain getDecorateMain(int id) {
        DecorateMain result = decorateMainMap.get(id);
        if (result == null) {
            logger.error("getDecorateMain error key = " + id);
        }
        return result;
    }
    public static ConcurrentHashMap<Integer, DecorateMain> getDecorateMainMap() { return decorateMainMap; }

    /**
     * 初始化广告配置表
     */
    public static Future<Void> initAdvideoMain() {
        String table = "advideo_main";
        Promise promise = Promise.promise();
        String sql = "select * from " + table + ";";
        MysqlTool.queryJsonArrayFromDb(MysqlClient.getCommonPool(), sql, new JsonArray(), res -> {
            if (res.succeeded()) {
                try {
                    ConcurrentHashMap<Integer, AdvideoMain> tmp = new ConcurrentHashMap<>();
                    JsonArray result = res.result();
                    logger.info("init " + table + " size:" + result.size());
                    for (int i = 0; i < result.size(); i++) {
                        AdvideoMain entity = new AdvideoMain(result.getJsonObject(i));
                        tmp.put(entity.getId(), entity);
                    }
                    advideoMainMap = tmp;
                    promise.complete();
                } catch (Exception e) {
                    logger.error("init " + table + " error exception:" + Tool.getException(e));
                    promise.fail(e);
                }
            } else {
                logger.error(res.cause().getMessage());
                promise.fail(res.cause());
            }
        });
        return promise.future();
    }

    public static AdvideoMain getAdvideoMain(int id) {
        AdvideoMain result = advideoMainMap.get(id);
        if (result == null) {
            logger.error("getAdvideoMain error key = " + id);
        }
        return result;
    }
    public static ConcurrentHashMap<Integer, AdvideoMain> getAdvideoMainMap() { return advideoMainMap; }

}
